package com.uinnova.product.eam.service.fx.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.binary.core.exception.BinaryException;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.google.common.collect.Lists;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.comm.model.es.AssetWarehouseDir;
import com.uinnova.product.eam.comm.model.es.EamArtifact;
import com.uinnova.product.eam.comm.model.es.EamArtifactElement;
import com.uinnova.product.eam.comm.model.es.EamCategory;
import com.uinnova.product.eam.db.bean.DiagramChangeData;
import com.uinnova.product.eam.feign.workable.FlowableFeign;
import com.uinnova.product.eam.feign.workable.entity.PorcessResponse;
import com.uinnova.product.eam.feign.workable.entity.TaskResponse;
import com.uinnova.product.eam.model.ArtifactConstraintVo;
import com.uinnova.product.eam.model.EamArtifactCiVo;
import com.uinnova.product.eam.model.bm.CheckResultInfo;
import com.uinnova.product.eam.model.bm.DiagramPrivateAndDesginData;
import com.uinnova.product.eam.model.bm.PushParams;
import com.uinnova.product.eam.model.constants.FlowableConstant;
import com.uinnova.product.eam.model.dto.EamHierarchyDto;
import com.uinnova.product.eam.model.enums.ArtifactRelation;
import com.uinnova.product.eam.model.enums.ArtifactType;
import com.uinnova.product.eam.model.enums.AssetType;
import com.uinnova.product.eam.model.enums.CategoryTypeEnum;
import com.uinnova.product.eam.model.vo.CheckAssertEditCiParam;
import com.uinnova.product.eam.model.vo.CheckAssertEditReq;
import com.uinnova.product.eam.model.vo.CheckAssertEditRes;
import com.uinnova.product.eam.model.vo.PushCheckVO;
import com.uinnova.product.eam.service.*;
import com.uinnova.product.eam.service.es.AssetWarehouseDirDao;
import com.uinnova.product.eam.service.es.EamCategoryDesignDao;
import com.uinnova.product.eam.service.es.IamsESCIPrivateSvc;
import com.uinnova.product.eam.service.fx.CheckConflictSvc;
import com.uinnova.product.eam.service.fx.ProcessCiRltSvc;
import com.uinnova.product.eam.service.fx.ProcessDiagramSvc;
import com.uinnova.product.vmdb.comm.model.ci.CCcCi;
import com.uinnova.product.vmdb.comm.model.ci.CCcCiClass;
import com.uinnova.product.vmdb.comm.model.ci.CcCi;
import com.uinnova.product.vmdb.comm.model.ci.CcCiAttrDef;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiClassInfo;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiInfo;
import com.uinnova.project.api.diagram.v2.client.ESDiagramApiClient;
import com.uinnova.project.base.diagram.comm.model.*;
import com.uino.api.client.cmdb.ICIClassApiSvc;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.cmdb.query.ESCISearchBean;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.base.TypeVo;
import com.uino.bean.permission.query.CSysUser;
import com.uino.util.sys.CheckAttrUtil;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CheckConflictSvcImpl implements CheckConflictSvc {

    @Autowired
    IEamArtifactColumnSvc artifactColumnSvc;
    @Autowired
    ProcessCiRltSvc processCiRltSvc;
    @Autowired
    IUserApiSvc iUserApiSvc;
    @Autowired
    IEamArtifactSvc artifactSvc;
    @Autowired
    ICIClassApiSvc iciClassApiSvc;
    @Autowired
    ICISwitchSvc ciSwitchSvc;
    @Autowired
    ESDiagramApiClient diagramApiClient;
    @Autowired
    EamCategorySvc eamCategorySvc;
    @Autowired
    IBmHierarchySvc hierarchySvc;
    @Resource
    AssetWarehouseDirDao assetWarehouseDirDao;
    @Autowired
    EamCategoryDesignDao categoryDesignDao;
    @Autowired
    private BmDiagramSvc bmDiagramSvc;
    @Autowired
    private FlowableFeign flowableFeign;
    @Autowired
    private IamsESCIPrivateSvc iamsESCIPrivateSvc;
    @Autowired
    ProcessDiagramSvc processDiagramSvc;

    @Override
    public List<PushCheckVO> checkProductNum(PushParams pushParams) {
        List<PushCheckVO> result = new ArrayList<>();
        List<ESDiagramDTO> diagramList = pushParams.getAllProcessDiagramInfo();

        if(CollectionUtils.isEmpty(diagramList)){
            return Collections.emptyList();
        }
        List<Long> artifactIds = new ArrayList<>();
        for (ESDiagramDTO diagramInfo : diagramList) {
            String viewType = diagramInfo.getDiagram().getViewType();
            if(!BinaryUtils.isEmpty(viewType)){
                artifactIds.add(Long.parseLong(viewType));
            }
        }
        if(BinaryUtils.isEmpty(artifactIds)){
            return Collections.emptyList();
        }
        //取出所有视图信息中的node节点
        List<ESDiagramModel> modelList = diagramList.stream().map(each -> each.getDiagram().getModelList()).flatMap(Collection::stream).collect(Collectors.toList());
        //视图中没有拖入分类 getNodeDataArray
        List<ESDiagramNode> nodeList = modelList.stream().map(ESDiagramModel::getNodeDataArray).filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList());
        Map<String, List<ESDiagramNode>> nodeGroup = nodeList.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(ESDiagramNode::getdEnergy));
        //查询所有制品ci分栏信息
        List<Integer> types = Lists.newArrayList(ArtifactType.CI_TYPE.val(), ArtifactType.ASSET_TYPE.val());
        Map<Long, List<EamArtifactElement>> artifactColumnMap = artifactColumnSvc.queryByIdsAndType(artifactIds, types);
        List<EamArtifact> artifacts = artifactSvc.queryArtifactListByIds(artifactIds, 1);
        Map<Long, EamArtifact> artifactMap = artifacts.stream().collect(Collectors.toMap(EamArtifact::getId, e -> e, (k1, k2) -> k2));
        Map<Long, List<ArtifactConstraintVo>> artifactClassMap = getArtifactClassNum(artifactColumnMap);
        //校验
        for (ESDiagramDTO diagramInfo : diagramList) {
            String viewType = diagramInfo.getDiagram().getViewType();
            if(BinaryUtils.isEmpty(viewType)){
                continue;
            }
            Long artifactId = Long.parseLong(viewType);
            String dEnergy = diagramInfo.getDiagram().getDEnergy();
            PushCheckVO checkVO = new PushCheckVO(dEnergy, diagramInfo.getDiagram().getName());
            if(BinaryUtils.isEmpty(artifactMap.get(artifactId))){
                throw new BinaryException("视图'"+diagramInfo.getDiagram().getName()+"'制品已被删除/取消发布!");
            } else {
                List<ArtifactConstraintVo> numList = BinaryUtils.isEmpty(artifactClassMap.get(artifactId))?Lists.newArrayList() : artifactClassMap.get(artifactId);
                List<ESDiagramNode> nodes = BinaryUtils.isEmpty(nodeGroup.get(dEnergy)) ? Lists.newArrayList() : nodeGroup.get(dEnergy);
                List<CheckResultInfo> data = getArtifactCheckInfo(numList, nodes);
                if(CollectionUtils.isEmpty(data)){
                    continue;
                }
                checkVO.setData(data);
            }
            result.add(checkVO);
        }
        return result;
    }

    @Override
    public List<PushCheckVO> checkRequiredField(PushParams pushParams) {
        List<PushCheckVO> result = new ArrayList<>();
        // 获取用户私有库/设计库数据
        Map<String, List<ESDiagramDTO>> allProcessDiagramMap = pushParams.getAllProcessDiagramMap();
        Map<String, DiagramPrivateAndDesginData> userDataMap = this.getUserData(allProcessDiagramMap);
        Map<String, List<ESDiagramNode>> diagramNodeMap = this.getDiagramNodeMap(pushParams.getAllProcessDiagramInfo());

        for (String userCode : userDataMap.keySet()) {     // 根据用户遍历
            DiagramPrivateAndDesginData data = userDataMap.get(userCode);
            if(BinaryUtils.isEmpty(data)){
                continue;
            }
            // 获取当前用户所有视图上的CI数据
            Long[] classIds = data.getPrivateCiInfos().stream().map(each -> each.getCi().getClassId()).toArray(Long[]::new);
            CCcCiClass cdt = new CCcCiClass();
            cdt.setIds(classIds);
            List<CcCiClassInfo> classInfoList = iciClassApiSvc.queryClassByCdt(cdt);
            Map<Long, CcCiClassInfo> classMap = classInfoList.stream().collect(Collectors.toMap(each -> each.getCiClass().getId(), each -> each, (k1, k2) -> k2));     // 分类ID 对应的 分类数据

            // 遍历对象结果 进行校验
            Map<String, String> errMap = new HashMap<>();       // 每个CI对应的校验结果
            Map<String, String> ciCodeAndClassNameMap = new HashMap<>();
            for (CcCiInfo ci : data.getPrivateCiInfos()) {
                List<CcCiAttrDef> defs = classMap.get(ci.getCi().getClassId()).getAttrDefs();
                String errorMsgs = CheckAttrUtil.validateAttrValTypeForEAPD(defs, ci.getAttrs());
                if (BinaryUtils.isEmpty(errorMsgs)) {
                    continue;
                }
                errMap.put(ci.getCi().getCiCode(), errorMsgs);
                ciCodeAndClassNameMap.put(ci.getCi().getCiCode(), getCIShowName(ci));
            }

            // 将校验结果组装为 视图id 对应的必填项缺失map结果集
            List<ESDiagramDTO> esDiagramDTOS = allProcessDiagramMap.get(userCode);

            for (ESDiagramDTO esDiagramDTO : esDiagramDTOS) {
                List<CheckResultInfo> newCheckData = new ArrayList<>();
                if (!BinaryUtils.isEmpty(diagramNodeMap.get(esDiagramDTO.getDiagram().getDEnergy()))) {
                    for (ESDiagramNode esDiagramNode : diagramNodeMap.get(esDiagramDTO.getDiagram().getDEnergy())) {
                        if (errMap.containsKey(esDiagramNode.getCiCode())) {
                            CheckResultInfo ckeckInfo = new CheckResultInfo();
                            ckeckInfo.setCiCode(esDiagramNode.getCiCode());
                            ckeckInfo.setCiPrimaryKey(ciCodeAndClassNameMap.get(esDiagramNode.getCiCode()));
                            ckeckInfo.setRequiredFieldInfo(errMap.get(esDiagramNode.getCiCode()));
                            newCheckData.add(ckeckInfo);
                        }
                    }
                }
                if (CollectionUtils.isEmpty(newCheckData)) {
                    continue;
                }
                PushCheckVO checkVO = new PushCheckVO(esDiagramDTO.getDiagram().getDEnergy(), esDiagramDTO.getDiagram().getName(), newCheckData);
                result.add(checkVO);
            }
        }
        return result;
    }

    private String getCIShowName(CcCiInfo ciInfo) {
        String ciLabel = ciInfo.getCi().getCiLabel();
        List<String> labels = JSONObject.parseArray(ciLabel, String.class);
        if (StringUtils.isBlank(ciLabel) || CollectionUtils.isEmpty(labels)) {
            return ciInfo.getCiClass().getClassName();
        }
        return String.join(",", labels);
    }

    @Override
    public List<PushCheckVO> checkPrimaryKey(PushParams pushParams) {
        Map<String, List<DiagramChangeData>> returnData = new HashMap<>();
        List<PushCheckVO> result = new ArrayList<>();
        Map<String, List<ESDiagramDTO>> allProcessDiagramMap = pushParams.getAllProcessDiagramMap();
        Map<String, DiagramPrivateAndDesginData> userData = this.getUserData(allProcessDiagramMap);
        Map<String, List<CcCiInfo>> dealCiMap = new ConcurrentHashMap<>();

        for (String userCode : allProcessDiagramMap.keySet()) {
            List<DiagramChangeData> nuptialData = new ArrayList<>();        // 当前用户的主键冲突数据 data

            DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId = userData.get(userCode);     // 当前用户的 私有库 / 设计库 数据
            if(privateAndDesginDataByDEnergyId == null){
                continue;
            }
            List<CcCiInfo> privateCiInfos = privateAndDesginDataByDEnergyId.getPrivateCiInfos();
            List<CcCiInfo> desginCiInfos = privateAndDesginDataByDEnergyId.getDesginCiInfos();
            if (privateCiInfos.size() == desginCiInfos.size() || BinaryUtils.isEmpty(privateCiInfos)) {
                // 当前数据都绑定到设计库 一一对应
                // returnData.put(userCode, nuptialData);
                continue;
            }

            // CI code与data对应的map
            Map<String, CcCiInfo> privateCodeAndCiInfoMap = new HashMap<>();
            Map<String, CcCiInfo> desginCodeAndCiInfoMap = new HashMap<>();
            for (CcCiInfo privateCI : privateCiInfos) {
                privateCodeAndCiInfoMap.put(privateCI.getCi().getCiCode(), privateCI);
            }
            for (CcCiInfo desginCI : desginCiInfos) {
                desginCodeAndCiInfoMap.put(desginCI.getCi().getCiCode(), desginCI);
            }
            // 筛选出设计库不存在的数据 name --ciCode不存在于设计库的私有库ci
            Map<String, CcCiInfo> existPrivateNameAndDataList = new HashMap<>();
            for (CcCiInfo privateCI : privateCiInfos) {
                if (!desginCodeAndCiInfoMap.containsKey(privateCI.getCi().getCiCode())) {
                    existPrivateNameAndDataList.put(privateCI.getCi().getCiPrimaryKey(), privateCI);
                }
            }
            //设计库根据名称查询是否存在同名要素
            List<ESCIInfo> nameEqualData = new ArrayList<>();

            if (MapUtils.isEmpty(existPrivateNameAndDataList)) {
                // 设计库导入导出可能存在异常数据 排除异常数据影响
//                returnData.put(userCode, nuptialData);
                continue;
            }
            List<String> ciPrimaryKeys = new ArrayList<>();
            List<Long> classIds = new ArrayList<>();
            existPrivateNameAndDataList.values().forEach(e -> {
                ciPrimaryKeys.add(e.getCi().getCiPrimaryKey());
                classIds.add(e.getCi().getClassId());
            });
            ESCISearchBean esciSearchBean = new ESCISearchBean();
            esciSearchBean.setCiPrimaryKeys(ciPrimaryKeys);
            esciSearchBean.setClassIds(classIds);
            esciSearchBean.setPageNum(1);
            esciSearchBean.setPageSize(500);
            //ciCode不存在于设计库的私有库ci 对应的同主键设计库ci列表
            Page<ESCIInfo> esciInfoPage = ciSwitchSvc.searchESCIByBean(esciSearchBean, LibType.DESIGN);
            nameEqualData.addAll(esciInfoPage.getData());
            if (CollectionUtils.isEmpty(nameEqualData)) {
                // 设计库无重名要素 不需要检出
                // returnData.put(userCode, nuptialData);
                continue;
            }

            //ciCode不存在于设计库的私有库ci 对应的同主键设计库ciCodes
            List<String> ciCodes = nameEqualData.stream().map(ESCIInfo::getCiCode).collect(Collectors.toList());
            CCcCi cdt = new CCcCi();
            cdt.setCiCodes(ciCodes.toArray(new String[ciCodes.size()]));

            List<CcCiInfo> ccCiInfos = ciSwitchSvc.queryCiInfoList(1L, cdt, null, false, true, LibType.DESIGN);

            for (CcCiInfo esciInfo : ccCiInfos) {
                CcCiInfo privateCiInfo = existPrivateNameAndDataList.get(esciInfo.getCi().getCiPrimaryKey());
                DiagramChangeData diagramChangeData = new DiagramChangeData(privateCiInfo, esciInfo, null, null);
                nuptialData.add(diagramChangeData);
                List<CcCiInfo> dealCis = dealCiMap.getOrDefault(userCode, new ArrayList<>());
                dealCis.add(privateCiInfo);
                dealCiMap.put(userCode, dealCis);
            }
            if (CollectionUtils.isEmpty(nuptialData)) {
                continue;
            }
            returnData.put(userCode, nuptialData);
        }

        List<ESDiagramDTO> allProcessDiagramInfo = pushParams.getAllProcessDiagramInfo();
        Map<String, List<ESDiagramNode>> diagramNodeMap = this.getDiagramNodeMap(allProcessDiagramInfo);

        if (MapUtils.isEmpty(returnData)) {
            return result;
        }
        for (ESDiagramDTO diagramInfo : allProcessDiagramInfo) {
            String energy = diagramInfo.getDiagram().getDEnergy();
            String ownerCode = diagramInfo.getDiagram().getOwnerCode();
            List<ESDiagramNode> nodeList = diagramNodeMap.get(energy);
            if(CollectionUtils.isEmpty(nodeList)){
                continue;
            }
            List<String> nodeCode = new ArrayList<>();
            if(!BinaryUtils.isEmpty(nodeList)){
                for (ESDiagramNode node : nodeList) {
                    if (!BinaryUtils.isEmpty(node.getCiCode())) {
                        nodeCode.add(node.getCiCode());
                    }
                }
            }
            if (returnData.containsKey(ownerCode)) {
                Map<String, ESCIInfo> unEditAuthSamePrimaryKey = getUnEditAuthSamePrimaryKey(dealCiMap, ownerCode);
                List<DiagramChangeData> diagramChangeData = returnData.get(ownerCode);
                Map<Long, String> replaceMap = new HashMap<>();
                List<ESCIInfo> updateInfo = new ArrayList<>();
                Set<Long> updateClassIds = new HashSet<>();
                Map<String, ESCIInfo> freshCodeMap = new HashMap<>();
                List<CheckResultInfo> dataList = new ArrayList<>();
                for (DiagramChangeData changeData : diagramChangeData) {
                    CcCi privateCi = changeData.getPrivateCiInfo().getCi();
                    if (nodeCode.contains(privateCi.getCiCode())) {
                        if (!unEditAuthSamePrimaryKey.containsKey(privateCi.getCiPrimaryKey())) {
                            CheckResultInfo data = new CheckResultInfo();
                            data.setPrivateCiPrimaryKey(changeData.getPrivateCiInfo().getCi().getCiPrimaryKey());
                            data.setDesignCiPrimaryKey(changeData.getDesginCiInfo().getCi().getCiPrimaryKey());
                            data.setPrivateIcon(changeData.getPrivateCiInfo().getCiClass().getIcon());
                            data.setDesignIcon(changeData.getDesginCiInfo().getCiClass().getIcon());
                            dataList.add(data);
                            continue;
                        }
                        ESCIInfo unEditAuthSamePrimaryKeyDesign = unEditAuthSamePrimaryKey.get(privateCi.getCiPrimaryKey());
                        //非资产创建者，主键校验时，设计库覆盖私有库
                        ESCIInfo updateCiInfo = EamUtil.tranESCIInfo(changeData.getPrivateCiInfo());
                        String ciCode = updateCiInfo.getCiCode();
                        replaceMap.put(updateCiInfo.getId(), unEditAuthSamePrimaryKeyDesign.getCiCode());
                        freshCodeMap.put(ciCode, unEditAuthSamePrimaryKeyDesign);
                        //私有库数据强制修改为设计库数据 发布版本修正为设计库版本 本地版本归0
                        updateCiInfo.setAttrs(unEditAuthSamePrimaryKeyDesign.getAttrs());
                        updateCiInfo.setCiCode(unEditAuthSamePrimaryKeyDesign.getCiCode());
                        updateCiInfo.setPublicVersion(unEditAuthSamePrimaryKeyDesign.getPublicVersion());
                        updateCiInfo.setLocalVersion(0L);
                        updateClassIds.add(updateCiInfo.getClassId());
                        updateInfo.add(updateCiInfo);
                    }
                    if (!org.springframework.util.CollectionUtils.isEmpty(freshCodeMap)) {
                        iamsESCIPrivateSvc.replaceCiCodeByIds(replaceMap);
                    }
                    if (!org.springframework.util.CollectionUtils.isEmpty(updateInfo)) {
                        ciSwitchSvc.saveOrUpdateBatchCI(updateInfo, new ArrayList<>(updateClassIds),
                                ownerCode, ownerCode, LibType.PRIVATE);
                        processDiagramSvc.freshDiagramNode(freshCodeMap, ownerCode);
                    }
                }

                if (!BinaryUtils.isEmpty(dataList)) {
                    result.add(new PushCheckVO(energy, diagramInfo.getDiagram().getName(), dataList));
                }
            }
        }
        return result;
    }

    private Map<String, ESCIInfo> getUnEditAuthSamePrimaryKey(Map<String, List<CcCiInfo>> dealCiMap, String ownerCode) {
        List<CcCiInfo> dealCis = dealCiMap.get(ownerCode);
        if (CollectionUtils.isEmpty(dealCis)) {
            return new ConcurrentHashMap<>();
        }
        List<CheckAssertEditCiParam> ciParams = new ArrayList<>();
        for (CcCiInfo ciInfo : dealCis) {
            CheckAssertEditCiParam ciParam = new CheckAssertEditCiParam();
            ciParam.setLibType(LibType.PRIVATE);
            //这里特殊处理下：发布校验只校验主键一致
            ciParam.setCiCode("empty");
            ciParam.setCiPrimaryKey(ciInfo.getCi().getCiPrimaryKey());
            ciParams.add(ciParam);
        }
        CheckAssertEditReq req = new CheckAssertEditReq();
        req.setFromDiagram(true);
        req.setOperator(ownerCode);
        req.setCiParams(ciParams);
        List<CheckAssertEditRes> assertEditRes = bmDiagramSvc.checkAssertEditAuth(req, false);
        if (CollectionUtils.isEmpty(assertEditRes)) {
            return new ConcurrentHashMap<>();
        }
        Map<String, ESCIInfo> sameKeyDesignCiInfoMap = new ConcurrentHashMap<>();
        for (CheckAssertEditRes res : assertEditRes) {
            if (res.getEdit() || res.getSameKeyDesignCiInfo() == null) {
                continue;
            }
            sameKeyDesignCiInfoMap.put(res.getCiPrimaryKey(), res.getSameKeyDesignCiInfo());
        }
        return sameKeyDesignCiInfoMap;
    }

    @Override
    public List<PushCheckVO> checkDiagramVersion(PushParams pushParams) {
        List<PushCheckVO> result = new ArrayList<>();
        List<ESDiagramDTO> allProcessDiagramInfo = pushParams.getAllProcessDiagramInfo();
        Map<String, ESDiagram> releaseDiagramMap = this.getReleaseDiagramInfo(allProcessDiagramInfo);
        if (BinaryUtils.isEmpty(releaseDiagramMap)) {
            // 查询到的设计库视图为空 就不需要进行试图版本对比
            return result;
        }

        for (ESDiagramDTO esDiagramDTO : allProcessDiagramInfo) {
            if (BinaryUtils.isEmpty(esDiagramDTO.getDiagram().getReleaseDiagramId())) {
                // 当前视图未发布
                continue;
            }
            ESDiagram releaseDiagramInfo = releaseDiagramMap.get(esDiagramDTO.getDiagram().getReleaseDiagramId());
            if (BinaryUtils.isEmpty(releaseDiagramInfo)) {
                // 兼容设计库异常视图
                continue;
            }
            // 查询当前视图发布的版本号
            if (Integer.valueOf(esDiagramDTO.getDiagram().getReleaseVersion()) < Integer.valueOf(releaseDiagramInfo.getReleaseVersion())) {
                // 本地版本低于发布版本 需要检出
                CheckResultInfo data = new CheckResultInfo();
                data.setCurrentVersion("V" + esDiagramDTO.getDiagram().getReleaseVersion());
                data.setLatestVersion("V" + releaseDiagramInfo.getReleaseVersion());
                result.add(new PushCheckVO(esDiagramDTO.getDiagram().getDEnergy(), esDiagramDTO.getDiagram().getName(), Collections.singleton(data)));
            }
        }
        return result;
    }

    @Override
    public Map<String, Object> checkCIVersion(PushParams pushParams) {
        Map<String, Object> returnData = new HashMap<>();

        Map<String, List<ESDiagramDTO>> allProcessDiagramMap = pushParams.getAllProcessDiagramMap();
        Map<String, DiagramPrivateAndDesginData> userData = this.getUserData(allProcessDiagramMap);

        for (String userCode : allProcessDiagramMap.keySet()) {
            List<DiagramChangeData> versionChangeData = new ArrayList<>();

            // 读取视图 CI 数据 判断版本
            List<CcCiInfo> privateCiInfos = userData.get(userCode).getPrivateCiInfos();
            List<CcCiInfo> desginCiInfos = userData.get(userCode).getDesginCiInfos();

            if (CollectionUtils.isEmpty(desginCiInfos)) {
                returnData.put(userCode, versionChangeData);       // 设计库数据为空 视图数据都为新建  当前用户的视图数据不存在版本冲突
            } else {
                // 判断私有库与设计库数据是否存在版本冲突
                Map<String, CcCiInfo> desginCodeAndDataInfos = new HashMap<>();
                for (CcCiInfo desginCI : desginCiInfos) {
                    desginCodeAndDataInfos.put(desginCI.getCi().getCiCode(), desginCI);
                }

                for (CcCiInfo privateCI : privateCiInfos) {
                    if (desginCodeAndDataInfos.containsKey(privateCI.getCi().getCiCode())) {
                        // 对比 localVersion 与 publishVersion
                        if (privateCI.getCi().getPublicVersion() < desginCodeAndDataInfos.get(privateCI.getCi().getCiCode()).getCi().getPublicVersion()) {
                            // 当前数据存在版本冲突
                            DiagramChangeData diagramChangeData = new DiagramChangeData(privateCI, desginCodeAndDataInfos.get(privateCI.getCi().getCiCode()), null, null);
                            versionChangeData.add(diagramChangeData);
                        }
                    }
                }
                returnData.put(userCode, versionChangeData);        // 记录着当前用户名下的冲突CI
            }
        }
        return returnData;
    }

    @Override
    public List<PushCheckVO> checkModelPlvlExist(PushParams pushParams) {
        List<PushCheckVO> result = new ArrayList<>();
        List<ESDiagramDTO> modelDiagramList = pushParams.getModelDiagramList();
        if (CollectionUtils.isEmpty(modelDiagramList)) {
            return result;
        }
        Set<String> userCodes = pushParams.getModelCategoryMap().keySet();
        // 获取模型视图所在的目录信息
        List<Long> modelDirIds = new ArrayList<>();
        for (ESDiagramDTO modelDiagram : modelDiagramList) {
            modelDirIds.add(modelDiagram.getDiagram().getDirId());
        }

        // 当前校验视图所属的目录信息
        List<EamCategory> privateCategoryList = eamCategorySvc.getByIds(modelDirIds, LibType.PRIVATE);
        if (CollectionUtils.isEmpty(privateCategoryList)) {
            return result;
        }
        Set<Long> modelIds = new HashSet<>();
        // 校验视图分别根据用户和模型分组
        Map<String, List<EamCategory>> privateCategoryUserCodeMap = privateCategoryList.stream().collect(Collectors.groupingBy(item -> item.getOwnerCode()));

        Map<String, List<Long>> userCodesModelId = new HashMap<>();
        for (String userCode : privateCategoryUserCodeMap.keySet()) {
            Set<Long> modelIdSet = privateCategoryUserCodeMap.get(userCode).stream().map(EamCategory::getModelId).collect(Collectors.toSet());
            userCodesModelId.put(userCode, new ArrayList<>(modelIdSet));
        }

        pushParams.setUserCodesModelIdMap(userCodesModelId);

        List<EamCategory> designCategories = eamCategorySvc.selectByModelIds(userCodesModelId, LibType.DESIGN);
        Map<Long, List<EamCategory>> designCategoriesModelIdMap = designCategories.stream().collect(Collectors.groupingBy(item -> item.getModelId()));
        Map<Long, Map<String, EamCategory>> modelCiCodeMap = new HashMap<>();
        for (Long modelId : designCategoriesModelIdMap.keySet()) {
            Map<String, EamCategory> ciCodeMap = new HashMap<>();
            for (EamCategory designCategory : designCategoriesModelIdMap.get(modelId)) {
                ciCodeMap.put(designCategory.getCiCode(), designCategory);
            }
            modelCiCodeMap.put(modelId, ciCodeMap);
        }
        pushParams.setDesignCategoryCiCodeModelIdMap(modelCiCodeMap);


        // 查询我的空间模型目录信息
        List<EamCategory> privateModelCategories = eamCategorySvc.selectByModelIds(userCodesModelId, LibType.PRIVATE);
        // 校验视图的所属模型树下的所有数据根据用户分组
        Map<String, List<EamCategory>> privateModelCategoryUserCodeMap = privateModelCategories.stream().collect(Collectors.groupingBy(item -> item.getOwnerCode()));
        pushParams.setPrivateModelCategoryUserCodeMap(privateModelCategoryUserCodeMap);

        Map<String, Map<Long, List<EamCategory>>> privateModelCategoryModelIdUserCodeMap = new HashMap<>();
        for (String userCode : privateModelCategoryUserCodeMap.keySet()) {
            Map<Long, List<EamCategory>> collect = privateModelCategoryUserCodeMap.get(userCode).stream().collect(Collectors.groupingBy(item -> item.getModelId()));
            privateModelCategoryModelIdUserCodeMap.put(userCode, collect);
        }
        pushParams.setPrivateModelCategoryModelIdUserCodeMap(privateModelCategoryModelIdUserCodeMap);

        Map<Long, EamCategory> privateModelMap = new HashMap<>();
        for (EamCategory privateCategory : privateModelCategories) {
            privateModelMap.put(privateCategory.getId(), privateCategory);
        }
        pushParams.setPrivateCategoryIdMap(privateModelMap);

        for (ESDiagramDTO modelDiagram : modelDiagramList) {
            Long dirId = modelDiagram.getDiagram().getDirId();
            EamCategory privateCategory = privateModelMap.get(dirId);
            //视图所在目录为模型根目录或上级目录为模型根目录
            if(privateCategory.getType() == 4 || 4 == privateModelMap.get(privateCategory.getParentId()).getType()){
                continue;
            }
            EamCategory parCategory = privateModelMap.get(privateCategory.getParentId());
            String msg = "";
            if(BinaryUtils.isEmpty(parCategory)){
                msg = "目录信息有误,请联系管理员!";
            } else {
                Map<String, EamCategory> eamCategoryMap = modelCiCodeMap.get(parCategory.getModelId());
                if(BinaryUtils.isEmpty(eamCategoryMap)){
                    msg = "请先发布当前'" + privateCategory.getDirName() + "'目录的上级目录,再发布当前目录或视图!";
                }else{
                    EamCategory category = eamCategoryMap.get(parCategory.getCiCode());
                    if (BinaryUtils.isEmpty(category)) {
                        msg = "请先发布当前'" + privateCategory.getDirName() + "'目录的上级目录,再发布当前目录或视图!";
                    }
                }

            }
            if (!BinaryUtils.isEmpty(msg)) {
                result.add(new PushCheckVO(modelDiagram.getDiagram().getDEnergy(), modelDiagram.getDiagram().getName(), msg));
            }
        }
        return result;
    }

    @Override
    public List<PushCheckVO> checkModelDiagramLocExist(PushParams pushParams) {
        List<PushCheckVO> result = new ArrayList<>();
        List<EamCategory> modelCategoryList = pushParams.getModelCategoryList();
        List<String> diagramIds = new ArrayList<>();
        for (EamCategory eamCategory : modelCategoryList) {
            if (!BinaryUtils.isEmpty(eamCategory.getDiagramId())) {
                diagramIds.add(eamCategory.getDiagramId());
            }
        }

        List<ESDiagramDTO> commonModelDiagramList = new ArrayList<>();
        for (ESDiagramDTO modelDiagram : pushParams.getModelDiagramList()) {
            if (!diagramIds.contains(modelDiagram.getDiagram().getDEnergy())) {
                commonModelDiagramList.add(modelDiagram);
            }
        }

        if(CollectionUtils.isEmpty(commonModelDiagramList)){
            return result;
        }
        //单图发布时校验当前视图所在目录是否发布
        if(!pushParams.getIsModelTree()){
            for (ESDiagramDTO each : commonModelDiagramList) {
                // 目录ID应该不会出现为0的情况
                if(each.getDiagram().getDirId().equals(0L)){
                    continue;
                }
                String msg = "";
                EamCategory privateCategory = pushParams.getPrivateCategoryIdMap().get(each.getDiagram().getDirId());
                if(BinaryUtils.isEmpty(privateCategory)){
                    msg = "当前模型视图所属目录信息异常";
                } else {
                    Map<Long, Map<String, EamCategory>> designCategoryCiCodeModelIdMap = pushParams.getDesignCategoryCiCodeModelIdMap();
                    if (BinaryUtils.isEmpty(designCategoryCiCodeModelIdMap)) {
                        msg = "请先发布模型目录或者模型视图!";
                    } else {
                        EamCategory designCategory = designCategoryCiCodeModelIdMap.get(privateCategory.getModelId()).get(privateCategory.getCiCode());
                        if(BinaryUtils.isEmpty(designCategory)){
                            msg = "请先发布模型目录或者模型视图!";
                        }
                    }
                }
                if (!BinaryUtils.isEmpty(msg)) {
                    result.add(new PushCheckVO(each.getDiagram().getDEnergy(), each.getDiagram().getName(), msg));
                }
            }
        }
        return result;
    }

    @Override
    public List<PushCheckVO> checkModelHierarchyComplete(PushParams pushParams) {
        Map<String, Object> returnData = new HashMap<>();
        List<PushCheckVO> result = new ArrayList<>();
        List<EamCategory> modelCategoryList = pushParams.getModelCategoryList();
        if (CollectionUtils.isEmpty(modelCategoryList)) {
            return result;
        }
        List<ESDiagramDTO> modelDiagramList = pushParams.getModelDiagramList();
        Map<Long, EamCategory> modelCategoryIdMap = modelCategoryList.stream().collect(Collectors.toMap(e -> e.getId(), e -> e, (k1, k2) -> k1));

        Map<String, List<Long>> userCodesModelIdMap = pushParams.getUserCodesModelIdMap();

        Set<Long> modelIds = new HashSet<>();
        if(!BinaryUtils.isEmpty(userCodesModelIdMap)){
            for (String userCode : userCodesModelIdMap.keySet()) {
                modelIds.addAll(userCodesModelIdMap.get(userCode));
            }
        }
        //查询校验视图使用到的层级配置
        List<EamHierarchyDto> eamHierarchyDtos = hierarchySvc.queryByModelIds(new ArrayList<>(modelIds));
        // 根据模型ID将数据分组
        Map<Long, List<EamHierarchyDto>> eamHierarchyModelIdMap = eamHierarchyDtos.stream().collect(Collectors.groupingBy(EamHierarchyDto::getModelId));

        Map<String, Map<Long, List<EamCategory>>> privateModelCategoryModelIdUserCodeMap = pushParams.getPrivateModelCategoryModelIdUserCodeMap();

        for (ESDiagramDTO esDiagramDTO : modelDiagramList) {
            Long dirId = esDiagramDTO.getDiagram().getDirId();
            String energyId = esDiagramDTO.getDiagram().getDEnergy();
            EamCategory privateCategory = modelCategoryIdMap.get(dirId);
            Long modelId = privateCategory.getModelId();
            String userCode = privateCategory.getOwnerCode();
            List<EamCategory> privateModelCategories = privateModelCategoryModelIdUserCodeMap.get(userCode).get(modelId);
            Integer startLvl = null;
            for (EamCategory eamCategory : privateModelCategories) {
                if (eamCategory.getType() == 4) {
                    startLvl = eamCategory.getDirLvl();
                }
            }
            Integer privateCategoryLvl = privateCategory.getDirLvl() - startLvl - 1;
            List<EamHierarchyDto> hierarchyList = eamHierarchyModelIdMap.get(modelId);
            Map<Integer, EamHierarchyDto> hierarchyLvlMap = hierarchyList.stream().collect(Collectors.toMap(e -> e.getDirLvl(), e -> e, (k1, k2) -> k1));
            EamHierarchyDto eamHierarchyDto = hierarchyLvlMap.get(privateCategoryLvl);
            if (BinaryUtils.isEmpty(eamHierarchyDto) || !eamHierarchyDto.getFlag()) {
                continue;
            }
            // 根据层级将数据分组
            Map<Integer, List<EamCategory>> lvlCategroyMap = privateModelCategories.stream().collect(Collectors.groupingBy(item -> item.getDirLvl()));
            if ((lvlCategroyMap.keySet().size()-1) < hierarchyList.size()) {
                result.add(new PushCheckVO(energyId, esDiagramDTO.getDiagram().getName(), "当前发布的模型层级不完整，请检查!"));
            }
        }
        return result;
    }

    @Override
    public List<PushCheckVO> checkPushLocation(PushParams pushParams) {
        List<PushCheckVO> result = new ArrayList<>();
        List<ESDiagramDTO> commonDiagramList = pushParams.getCommonDiagramList();
        String msg = "您所选文件，暂无权限发布到该资产目录，请联系管理员！";
        if (!CollectionUtils.isEmpty(commonDiagramList)) {
            // 普通视图校验
            List<String> releaseDiagramIds = new ArrayList<>();
            for (ESDiagramDTO esDiagramDTO : commonDiagramList) {
                String releaseDiagramId = esDiagramDTO.getDiagram().getReleaseDiagramId();
                if (!BinaryUtils.isEmpty(releaseDiagramId)) {
                    releaseDiagramIds.add(releaseDiagramId);
                }
            }
            if (!CollectionUtils.isEmpty(releaseDiagramIds)) {
                List<ESDiagram> releaseDiagrams = diagramApiClient.queryDBDiagramInfoByIds(releaseDiagramIds.toArray(new String[0]));
                Map<String, ESDiagram> idMap = releaseDiagrams.stream().collect(Collectors.toMap(ESDiagram::getDEnergy, e->e, (k1, k2)->k1));

                List<Long> designDirs = releaseDiagrams.stream().map(ESDiagram::getDirId).collect(Collectors.toList());
                List<EamCategory> designInfo = eamCategorySvc.getByIds(designDirs, LibType.DESIGN);
                Set<Long> rootDirs = new HashSet<>();
                Map<Long, Long> dirIdAndRootMap = new HashMap<>();
                for (EamCategory designDir : designInfo) {
                    String dirPath = designDir.getDirPath();
                    String[] dirIds = dirPath.split("#");
                    Long rootDirId = Long.valueOf(dirIds[1]);
                    rootDirs.add(rootDirId);
                    dirIdAndRootMap.put(designDir.getId(), rootDirId);
                }
                // List<EamCategory> rootDirInfo = eamCategorySvc.getByIds(rootDirs, LibType.DESIGN);

                Map<String, AssetWarehouseDir> modUrlMap = this.getSysModuleMap(rootDirs);

                for (ESDiagramDTO esDiagramDTO : commonDiagramList) {
                    String energy = esDiagramDTO.getDiagram().getDEnergy();
                    String releaseDiagramId = esDiagramDTO.getDiagram().getReleaseDiagramId();
                    if (BinaryUtils.isEmpty(releaseDiagramId)) {
                        continue;
                    }
                    ESDiagram releaseDiagram = idMap.get(releaseDiagramId);
                    if (BinaryUtils.isEmpty(releaseDiagram)) {
                        continue;
                    }
                    Long dirId = releaseDiagram.getDirId();
                    if (BinaryUtils.isEmpty(dirId)) {
                        continue;
                    }
                    Long rootId = dirIdAndRootMap.get(dirId);
                    if (BinaryUtils.isEmpty(rootId)) {
                        result.add(new PushCheckVO(energy, esDiagramDTO.getDiagram().getName(), msg));
                    } else {
                        for (String modUrl : modUrlMap.keySet()) {
                            if (modUrl.contains(rootId.toString())) {
                                AssetWarehouseDir sysModule = modUrlMap.get(modUrl);
                                boolean flag = this.checkAssetType(sysModule, AssetType.DIAGRAM, energy);
                                if (!flag) {
                                    result.add(new PushCheckVO(energy, esDiagramDTO.getDiagram().getName(), msg));
                                }
                            }
                        }
                    }
                }
            }
        }
        List<ESDiagramDTO> modelDiagramList = pushParams.getModelDiagramList();
        if (!CollectionUtils.isEmpty(modelDiagramList)) {
            // 获取模型视图所属的modelId
            List<String> modelDiagramIds = pushParams.getModelDiagramIds();
            List<ESDiagram> esDiagrams = diagramApiClient.queryDBDiagramInfoByIds(modelDiagramIds.toArray(new String[0]));
            List<Long> dirIds = esDiagrams.stream().map(ESDiagram::getDirId).collect(Collectors.toList());
            List<EamCategory> privateCategroyList = eamCategorySvc.getByIds(dirIds, LibType.PRIVATE);
            Map<Long, EamCategory> privateCategroyMap = privateCategroyList.stream().collect(Collectors.toMap(e->e.getId(), e->e, (k1, k2)->k1));
            Set<Long> modelIds = privateCategroyList.stream().map(EamCategory::getModelId).collect(Collectors.toSet());
            // 资产仓库获取模型
            BoolQueryBuilder bool = QueryBuilders.boolQuery();
            bool.must(QueryBuilders.termsQuery("modelId", modelIds));
            bool.must(QueryBuilders.termQuery("type", CategoryTypeEnum.MODEL_ROOT.val()));
            List<EamCategory> modelDirInfo = categoryDesignDao.getListByQuery(bool);
            if (!CollectionUtils.isEmpty(modelDirInfo)) {
                Set<Long> rootDirs = new HashSet<>();
                Map<Long, Long> modelIdAndRootMap = new HashMap<>();
                for (EamCategory designDir : modelDirInfo) {
                    String dirPath = designDir.getDirPath();
                    String[] dirIdStrs = dirPath.split("#");
                    Long rootDirId = Long.valueOf(dirIdStrs[1]);
                    rootDirs.add(rootDirId);
                    modelIdAndRootMap.put(designDir.getModelId(), rootDirId);
                }
                // 菜单节点信息
                Map<String, AssetWarehouseDir> sysModuleMap = this.getSysModuleMap(rootDirs);
                for (ESDiagramDTO modelDiagram : modelDiagramList) {
                    Long dirId = modelDiagram.getDiagram().getDirId();
                    EamCategory privateCategroy = privateCategroyMap.get(dirId);
                    if (BinaryUtils.isEmpty(privateCategroy)) {
                        continue;
                    }
                    Long modelId = privateCategroy.getModelId();
                    Long rootId = modelIdAndRootMap.get(modelId);
                    if (BinaryUtils.isEmpty(rootId)) {
                        result.add(new PushCheckVO(modelDiagram.getDiagram().getDEnergy(), modelDiagram.getDiagram().getName(), msg));
                    } else {
                        for (String modUrl : sysModuleMap.keySet()) {
                            if (modUrl.contains(rootId.toString())) {
                                AssetWarehouseDir sysModule = sysModuleMap.get(modUrl);
                                boolean flag = this.checkAssetType(sysModule, AssetType.MODEL, modelId.toString());
                                if (!flag) {
                                    result.add(new PushCheckVO(modelDiagram.getDiagram().getDEnergy(), modelDiagram.getDiagram().getName(), msg));
                                }
                            }
                        }
                    }
                }
            }
        }
        return result;
    }

    /**
     *  根据根目录ID 获取菜单信息map
     * @param rootDirs
     * @return
     */
    private Map<String, AssetWarehouseDir> getSysModuleMap(Set<Long> rootDirs) {
        Map<String, AssetWarehouseDir> modUrlMap = new HashMap<>();
        if (CollectionUtils.isEmpty(rootDirs)) {
            return modUrlMap;
        }
        BoolQueryBuilder bool = QueryBuilders.boolQuery();
        for (Long rootId : rootDirs) {
            bool.must(QueryBuilders.wildcardQuery("moduleUrl.keyword", "*" + rootId + "*"));
        }
        List<AssetWarehouseDir> listByQuery = assetWarehouseDirDao.getListByQuery(bool);
        modUrlMap = listByQuery.stream().collect(Collectors.toMap(AssetWarehouseDir::getModuleUrl, e->e, (k1, k2)->k1));
        return modUrlMap;
    }

    private boolean checkAssetType(AssetWarehouseDir library, AssetType type, String assetId) {
        List<Integer> assetTypes = library.getAssetType();
        //资产仓库菜单无当前资产类型
        if (org.springframework.util.CollectionUtils.isEmpty(assetTypes) || !assetTypes.contains(type.assetType)) {
            return false;
        }
        //获取资产类型id
        Long assetTypeId = this.getAssetTypeId(type, assetId);
        switch (type) {
            case SCHEME:
                Set<Long> templateIds = library.getSchemeList().stream().map(TypeVo::getId).collect(Collectors.toSet());
                return org.springframework.util.CollectionUtils.isEmpty(templateIds) || templateIds.contains(assetTypeId);
            case DIAGRAM:
                //这里需要注意下：自由视图默认0L
                Set<Long> artifactIds = library.getDiagramList().stream().map(TypeVo::getId).collect(Collectors.toSet());
                return org.springframework.util.CollectionUtils.isEmpty(artifactIds) || artifactIds.contains(assetTypeId);
            case MODEL:
                Set<Long> modelIds = library.getModelList().stream().map(TypeVo::getId).collect(Collectors.toSet());
                return org.springframework.util.CollectionUtils.isEmpty(modelIds) || modelIds.contains(assetTypeId);
            default:
                return false;
        }
    }

    private Long getAssetTypeId(AssetType type, String assetId) {
        //方案or模型
        if (type == AssetType.SCHEME || type == AssetType.MODEL) {
            return Long.valueOf(assetId);
        }
        String[] diagramIds = new String[]{assetId};
        List<ESDiagram> diagrams = diagramApiClient.queryDBDiagramInfoByIds(diagramIds);
        if (CollectionUtils.isEmpty(diagrams)) {
            throw new BinaryException("未找到视图");
        }
        ESDiagram diagram = diagrams.get(0);
        //视图
        if (diagram.getDiagramSubType() != null) {
            //自由视图
            if (diagram.getDiagramSubType() == 1) {
                return 0L;
            }
            //制品视图
            if (diagram.getDiagramSubType() == 2) {
                //返回制品id
                return Long.valueOf(diagram.getViewType());
            }
        }
        return -1L;
    }

    /**
     * 组装每个制品分栏中架构分类限制条件
     * @param artifactMap 制品map
     * @return Map<制品id, 分类数量限制信息>
     */
    private Map<Long, List<ArtifactConstraintVo>> getArtifactClassNum(Map<Long, List<EamArtifactElement>> artifactMap){
        Map<Long, List<ArtifactConstraintVo>> result = new HashMap<>(16);
        for (Map.Entry<Long, List<EamArtifactElement>> artifact : artifactMap.entrySet()) {
            List<EamArtifactElement> columns = artifact.getValue();
            List<ArtifactConstraintVo> numList = new ArrayList<>();
            List<String> elements = columns.stream().map(EamArtifactElement::getElements).flatMap(Collection::stream).collect(Collectors.toList());
            Map<String, EamArtifactCiVo> artifactCiMap = elements.stream().map(s -> JSON.parseObject(s, EamArtifactCiVo.class)).collect(Collectors.toMap(e->e.getId()+(BinaryUtils.isEmpty(e.getUnique()) ? "" : e.getUnique()), each->each,(k1, k2)->k2));
            for (EamArtifactCiVo vo : artifactCiMap.values()) {
                ArtifactConstraintVo constraint = new ArtifactConstraintVo();
                constraint.setKey(vo.getId() + (BinaryUtils.isEmpty(vo.getUnique()) ? "" : vo.getUnique()));
                constraint.setLabelName(vo.getViewName());
                constraint.setRelation(vo.getRelation());
                constraint.setViewNumber(vo.getViewNumber());
                numList.add(constraint);
            }
            result.put(artifact.getKey(), numList);
        }
        log.info("###### 打印后端解析制品约束规则：result【{}】", JSONObject.toJSONString(result));
        return result;
    }

    /**
     *  获取制品的校验信息
     * @param numList
     * @param nodes
     * @return
     */
    private List<CheckResultInfo> getArtifactCheckInfo(List<ArtifactConstraintVo> numList, List<ESDiagramNode> nodes){
        Map<String, Integer> shapeGroup = new HashMap<>(16);
        for (ESDiagramNode node : nodes) {
            if(BinaryUtils.isEmpty(node.getNodeJson())){
                continue;
            }
            JSONObject nodeJson = JSON.parseObject(node.getNodeJson());
            String nodeKey = nodeJson.getString("classId");
            String unique = nodeJson.getString("unique");
            if (!BinaryUtils.isEmpty(unique)) {
                // 同名分类 使用这个时间区分一下
                nodeKey = nodeKey + unique;
            }
            if(BinaryUtils.isEmpty(nodeKey)){
                nodeKey = nodeJson.getString("id");
                if(BinaryUtils.isEmpty(nodeKey)){
                    continue;
                }
            }
            shapeGroup.compute(nodeKey, (key, value)-> BinaryUtils.isEmpty(value)?1:++value);
        }
        log.info("###### 打印后端解析视图内的节点详情：shapeGroup【{}】", JSONObject.toJSONString(shapeGroup));
        List<CheckResultInfo> data = new ArrayList<>();
        for (ArtifactConstraintVo constraint : numList) {
            CheckResultInfo checkInfo = new CheckResultInfo();
            String key = constraint.getKey();
            Integer viewNum = constraint.getViewNumber();
            Integer num = BinaryUtils.isEmpty(shapeGroup.get(key)) ? 0 : shapeGroup.get(key);
            checkInfo.setClassName(constraint.getLabelName());
            String msg = "";
            if (constraint.getRelation().equals(ArtifactRelation.EQUALS.val()) && !num.equals(viewNum)) {
                msg = "实例个数必须为" + viewNum;
            } else if (constraint.getRelation().equals(ArtifactRelation.GREAT.val()) && num < viewNum) {
                msg = "实例个数必须大于或等于" + viewNum;
            } else if (constraint.getRelation().equals(ArtifactRelation.LESS.val()) && num > viewNum) {
                msg = "实例个数必须小于或等于" + viewNum;
            }
            if (BinaryUtils.isEmpty(msg)) {
                continue;
            }
            checkInfo.setProductNumInfo(msg);
            data.add(checkInfo);
        }
        return data;
    }

    /**
     *  获取用户私有库/设计库信息
     * @return
     */
    public Map<String, DiagramPrivateAndDesginData> getUserData(Map<String, List<ESDiagramDTO>> processDiagramMap) {
        Map<String, DiagramPrivateAndDesginData> userData = new HashMap<>();
        String[] loginCodeArr = processDiagramMap.keySet().toArray(new String[0]);
        if (loginCodeArr.length > 0) {
            CSysUser sysUser = new CSysUser();
            sysUser.setLoginCodes(loginCodeArr);
            List<SysUser> sysUserByCdt = iUserApiSvc.getSysUserByCdt(sysUser);
            Map<String, SysUser> userMap = sysUserByCdt.stream().collect(Collectors.toMap(SysUser::getLoginCode, e -> e, (k1, k2) -> k1));
            for (String userCode : userMap.keySet()) {
                DiagramPrivateAndDesginData privateAndDesginDataByDEnergyId = processCiRltSvc.getPrivateAndDesginDataByDEnergyId(processDiagramMap.get(userCode), userMap.get(userCode));
                if (BinaryUtils.isEmpty(privateAndDesginDataByDEnergyId)) {
                    continue;
                }
                userData.put(userCode, privateAndDesginDataByDEnergyId);
            }
        }
        return userData;
    }

    /**
     *  根据视图信息获取视图与视图内的节点的map信息
     */
    public Map<String, List<ESDiagramNode>> getDiagramNodeMap(List<ESDiagramDTO> esDiagramDTOS) {
        List<Long> ids = esDiagramDTOS.stream().map(diagram -> diagram.getDiagram().getId()).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(ids)) {
            return new HashMap<>();
        }
        List<ESDiagramNode> nodeList = diagramApiClient.selectNodeByDiagramIds(ids);
        // 根据视图ID去做分离node数据
        return nodeList.stream().collect(Collectors.groupingBy(ESDiagramNode::getdEnergy));
    }

    /**
     *  根据视图ID获取对应的发布状态的视图信息
     * @return
     */
    public Map<String, ESDiagram> getReleaseDiagramInfo(List<ESDiagramDTO> processDiagramList) {
        List<String> releaseDiagramList = new ArrayList<>();
        for (ESDiagramDTO esDiagramDTO : processDiagramList) {
            if (!BinaryUtils.isEmpty(esDiagramDTO.getDiagram().getReleaseDiagramId())) {
                releaseDiagramList.add(esDiagramDTO.getDiagram().getReleaseDiagramId());
            }
        }

        Map<String, ESDiagram> releaseDiagramMap = new HashMap<>();
        if (CollectionUtils.isEmpty(releaseDiagramList)) {
            return releaseDiagramMap;
        }
        List<ESDiagram> esDiagrams = diagramApiClient.queryDBDiagramInfoByIds(releaseDiagramList.toArray(new String[0]));
        for (ESDiagram esDiagramDTO : esDiagrams) {
            releaseDiagramMap.put(esDiagramDTO.getDEnergy(), esDiagramDTO);
        }
        return releaseDiagramMap;
    }

    @Override
    public void checkProcessStartUserIsCurUserCaseUnPassSubmit(PushParams pushParams) {
        List<ESDiagramDTO> allProcessDiagramInfo = pushParams.getAllProcessDiagramInfo();
        if (CollectionUtils.isEmpty(allProcessDiagramInfo)) {
            return;
        }
        for (ESDiagramDTO diagramDTO : allProcessDiagramInfo) {
            ESDiagramInfoDTO diagram = diagramDTO.getDiagram();
            //只看流程中的
            if (diagram == null || diagram.getFlowStatus() == null || diagram.getFlowStatus() != 1) {
                continue;
            }
            TaskResponse taskResponse = flowableFeign.getCurrentTaskDefinitionInfo(diagram.getDEnergy(), FlowableConstant.DIAGRAM_DEFINITION_KEY);
            if (taskResponse == null || StringUtils.isBlank(taskResponse.getProcessInstanceId())) {
                continue;
            }
            PorcessResponse porcessResponse = flowableFeign.getProcessInstanceByProcessInstanceId(taskResponse.getProcessInstanceId());
            if (porcessResponse == null || StringUtils.isBlank(porcessResponse.getProcessStartUserId())) {
                continue;
            }
            String curLoginCode = SysUtil.getCurrentUserInfo().getLoginCode();
            if (curLoginCode.equals(porcessResponse.getProcessStartUserId())) {
                continue;
            }
            //驳回流程提交人不是流程发起人，提示：xxx已提交评审，请联系该用户处理
            String processStartUserName = porcessResponse.getProcessStartUserId();
            CSysUser cdt = new CSysUser();
            cdt.setLoginCodeEqual(porcessResponse.getProcessStartUserId());
            List<SysUser> users = iUserApiSvc.getSysUserByCdt(cdt);
            if (!org.springframework.util.CollectionUtils.isEmpty(users)) {
                processStartUserName = users.get(0).getUserName();
            }
            throw new BinaryException(processStartUserName + "已提交评审，请联系该用户处理");
        }
    }
}
